home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / mq < prev    next >
Encoding:
Internet Message Format  |  1989-03-05  |  28.8 KB

  1. Subject:  v18i001:  Display mail queue and "from" output
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Kevin Sweet <sweet@scubed.arpa>
  6. Posting-number: Volume 18, Issue 2
  7. Archive-name: mq
  8.  
  9. Replacements for mailq and from:
  10.  
  11. mq -    selectively display the mail queue. 
  12.     options exist to list mail from or to a particular site, list 
  13.     mail exclusive of a particular site, and list mail without the 
  14.     truncation of long pathnames.
  15.  
  16. from -    makes `from' output look somewhat like `Mail' "header" output 
  17.     in that it prints out a minimalistic pathname to the sender and 
  18.     the subject line. It catches subject titles that `Mail' some-
  19.     times misses like news articles saved in mbox format. 
  20.  
  21. I have listed the machine/OS combinations (BSD/SysV) that I have 
  22. successfully compiled and run the programs in the Makefile. 
  23.  
  24. One comment, however.  No checking is done with respect to what other 
  25. programs (or users) are doing to the mail queue files and mailboxes. 
  26. (I have received segmentation faults _occasionally_ when, I assume, 
  27.  `sendmail' is deleting a file that `mq' wants to read. I'm a scientific
  28.  programmer that did this for "fun" and don't know what to do about this
  29.  situation. `From' seems to be pretty resilient, though.)
  30.  
  31. Kevin Sweet
  32. --
  33. Kevin Sweet ----------------------------------------- sweet@scubed.arpa
  34. S-CUBED, 3398 Carmel Mountain,  San Diego, CA 92121-1095, (619)587-8499
  35. (home)  12205 Carmel Vista 242, San Diego, CA 92130-2237, (619)259-9338
  36. UUCP/ARPA:            [ames,att,harvard,rutgers,ucsd,uunet]scubed!sweet
  37. DECNET:                         SDSC::"SWEET@S3VAX.SPAN" , 1.312::SWEET
  38.  
  39. #---cut here---cut here---cut here---cut here---cut here---cut here---
  40. #! /bin/sh
  41. # This is a shell archive, meaning:
  42. #     1. Remove everything above the #! /bin/sh line.
  43. #     2. Save the resulting text in a file.
  44. #     3. Execute the file with /bin/sh (not csh) to create:
  45. #        README
  46. #        Makefile
  47. #        mq.c
  48. #        from.c
  49. #        from.1
  50. #        mq.8
  51. #
  52. echo shar: extracting "README" '(1426 characters)'
  53. if test -f README
  54. then
  55.   echo shar: will not over-write existing file "README"
  56. else
  57. sed 's/^XX//' << \SHAR_EOF > README
  58. XXReplacements for mailq and from:
  59. XX
  60. XXmq -    selectively display the mail queue. 
  61. XX    options exist to list mail from or to a particular site, list 
  62. XX    mail exclusive of a particular site, and list mail without the 
  63. XX    truncation of long pathnames.
  64. XX
  65. XXfrom -    makes `from' output look somewhat like `Mail' "header" output 
  66. XX    in that it prints out a minimalistic pathname to the sender and 
  67. XX    the subject line. It catches subject titles that `Mail' some-
  68. XX    times misses like news articles saved in mbox format. 
  69. XX
  70. XXI have listed the machine/OS combinations (BSD/SysV) that I have 
  71. XXsuccessfully compiled and run the programs in the Makefile. 
  72. XX
  73. XXOne comment, however.  No checking is done with respect to what other 
  74. XXprograms (or users) are doing to the mail queue files and mailboxes. 
  75. XX(I have received segmentation faults _occasionally_ when, I assume, 
  76. XX `sendmail' is deleting a file that `mq' wants to read. I'm a scientific
  77. XX programmer that did this for "fun" and don't know what to do about this
  78. XX situation. `From' seems to be pretty resilient, though.)
  79. XX
  80. XXKevin Sweet, 22 April 1988
  81. XX--
  82. XXKevin Sweet ----------------------------------------- sweet@scubed.arpa
  83. XXS-CUBED, 3398 Carmel Mountain,  San Diego, CA 92121-1095, (619)587-8499
  84. XX(home)  12205 Carmel Vista 242, San Diego, CA 92130-2237, (619)259-9338
  85. XXUUCP/ARPA:            [ames,att,harvard,rutgers,ucsd,uunet]scubed!sweet
  86. XXDECNET:                         SDSC::"SWEET@S3VAX.SPAN" , 1.312::SWEET
  87. SHAR_EOF
  88. if test 1426 -ne "`wc -c < README`"
  89. then
  90.   echo shar: error transmitting "README" '(should have been 1426 characters)'
  91. fi
  92. fi # end of overwriting check
  93. echo shar: extracting "Makefile" '(1345 characters)'
  94. if test -f Makefile
  95. then
  96.   echo shar: will not over-write existing file "Makefile"
  97. else
  98. sed 's/^XX//' << \SHAR_EOF > Makefile
  99. XX# `C' compiler void compatibility
  100. XXVOID='-DVOID=(void)'
  101. XX
  102. XX# BSD compatibility
  103. XX# kelvin.arpa: Celerity C1230/C1260 UNIX 3.4.78
  104. XX# scubed.arpa: Ultrix V2.0-1
  105. XX# s3sun.arpa: Sun UNIX 4.2 Release 3.0
  106. XX# s3dawn.scubed.arpa: Sun UNIX 4.2 Release 3.4
  107. XX
  108. XX## SysV compatitibilty
  109. XX## space.scubed.arpa: Ridge 32/3200 running RX/V 1.1 (V.2)
  110. XX## sdcc15.ucsd.edu: UNIX System V Release 2.1.1v4 AT&T 3B20
  111. XX#NDIR=    -I/usr/local
  112. XX#LIBNDIR= -L/usr/local/lib -lndir
  113. XX## if the default set-up for the directory files doesn't work, 
  114. XX## `$man directory' should tell you where the appropriate files are 
  115. XX## located on your system (if they are there at all). Comment out the 
  116. XX## above two lines and adjust $(LIBNDIR) below as well as changing the 
  117. XX## include line in mq.c to the appropriate value. 
  118. XX##LIBNDIR= -L/usr/ucb.lib -lucb
  119. XX#OS=    -DSYSV $(NDIR)
  120. XX
  121. XX# system mailbox directory (the trailing slash is needed) and
  122. XX# system mail queue directory (no trailing slash!)
  123. XXMAIL=    '-DMAILDIR="/usr/spool/mail/"' '-DMQUEUE="/usr/spool/mqueue"'
  124. XX
  125. XXCFLAGS=    -O $(OS) $(VOID) $(MAIL)
  126. XX
  127. XXall:    mq from
  128. XX
  129. XXmq:    mq.o
  130. XX    cc -o mq mq.o $(LIBNDIR)
  131. XX
  132. XXfrom:    from.o
  133. XX    cc -o from from.o
  134. XX
  135. XXclean:    Makefile
  136. XX    @rm -f core mq.o from.o
  137. XX
  138. XXclobber: clean
  139. XX    @rm -f mq from mq.shar
  140. XX
  141. XXcleanse: clean shar
  142. XX    @rm -f mq from mq.c from.c mq.8 from.1 README Makefile
  143. XX
  144. XXshar:    Makefile
  145. XX    shar README Makefile mq.c from.c from.1 mq.8 > mq.shar
  146. SHAR_EOF
  147. if test 1345 -ne "`wc -c < Makefile`"
  148. then
  149.   echo shar: error transmitting "Makefile" '(should have been 1345 characters)'
  150. fi
  151. fi # end of overwriting check
  152. echo shar: extracting "mq.c" '(9946 characters)'
  153. if test -f mq.c
  154. then
  155.   echo shar: will not over-write existing file "mq.c"
  156. else
  157. sed 's/^XX//' << \SHAR_EOF > mq.c
  158. XX/* program for selectively displaying the mail queue. 
  159. XX *
  160. XX * usage:
  161. XX *    mq [-w] [-n] [-v] [-f [name]] [-t [name]] [-d name]
  162. XX *
  163. XX * caveats/comments:
  164. XX *    -> 1) no checking is done w.r.t. what other programs are doing 
  165. XX *          to the mail queue files.
  166. XX *       2) items in the queue without a control file are ignored and 
  167. XX *          not counted. 
  168. XX *       3) one might also want to sort by priority.
  169. XX *
  170. XX * author:
  171. XX *    Kevin Sweet ---------------------------------- sweet@scubed.arpa
  172. XX *    S-CUBED, 3398 Carmel Mountain,  San Diego, CA 92121-1095
  173. XX *    (home)  12205 Carmel Vista 242, San Diego, CA 92130-2237
  174. XX *    ------- [ames,att,harvard,rutgers,ucsd,uunet]scubed!sweet ------
  175. XX *
  176. XX * This work is copyright 1988 by Kevin Sweet. Permission is granted 
  177. XX * to modify and distribute this work under the provision that the 
  178. XX * author is informed of any non-cosmetic changes to the code and that 
  179. XX * the author's name remain part of the documentaion. 
  180. XX */
  181. XX
  182. XX#ifndef VOID
  183. XX# define VOID
  184. XX#endif
  185. XX#include <sys/types.h>
  186. XX#include <sys/stat.h>
  187. XX#ifdef SYSV
  188. XX# include <string.h>
  189. XX# define index        strchr
  190. XX# define rindex        strrchr
  191. XX# include <ndir.h>    /* see Makefile... */
  192. XX#else /* SYSV */
  193. XX# include <strings.h>
  194. XX# include <sys/dir.h>
  195. XX#endif
  196. XX#include <stdio.h>
  197. XX#include <ctype.h>
  198. XX
  199. XXint order();
  200. XXextern int free(), qsort();
  201. XXextern long atol();
  202. XXextern char *ctime(), *getenv(), *malloc();
  203. XXstatic int gethelp();
  204. XX
  205. XX#define FALSE        0
  206. XX#define LSIZE        256
  207. XX#define MALLOC(a)    (char *) malloc( (unsigned) sizeof(char) * \
  208. XX                             ((a) + 1) )
  209. XX#define NUMQ        128
  210. XX/* #define SORT_BY_ID    /**/
  211. XX#define SORT_BY_TIME    /**/
  212. XX#define SWITCHAR    '-'
  213. XX#define TRUE        1
  214. XX
  215. XXstruct mqueue {
  216. XX    long l;        /* location in directory stream */
  217. XX    long t;        /* time entered queue */
  218. XX    char q[8];    /* queue id */
  219. XX};
  220. XXtypedef unsigned short int BOOLEAN;
  221. XX
  222. XXmain(argc, argv)
  223. XXint argc;
  224. XXchar *argv[];
  225. XX{
  226. XX    BOOLEAN DONT, FROM, NUMBER, TO, VERBOSE, WIDE;
  227. XX    DIR *dp;
  228. XX    FILE *fp;
  229. XX    char dont[80], from[80], line[LSIZE], to[80];
  230. XX    register char *cp, *fg, *message, *qdir, *user;
  231. XX    register int i, icnt, ldont, lfrom, lto, mcnt, qcnt, qdlen;
  232. XX    register long size;
  233. XX    struct direct *dirp;
  234. XX    struct mqueue qinfo[NUMQ];
  235. XX    struct stat sbuf;
  236. XX
  237. XX    /* find the print options
  238. XX     */
  239. XX#ifdef SYSV
  240. XX    user = getenv("LOGNAME");
  241. XX#else
  242. XX    user = getenv("USER");
  243. XX#endif
  244. XX    DONT = FROM = NUMBER = TO = VERBOSE = WIDE = FALSE;
  245. XX    for (i = 1, cp = argv[1]; i < argc; i++, cp = argv[i]) 
  246. XX    if (cp[0] == SWITCHAR) 
  247. XX    switch (cp[1]) {
  248. XX        case 'h': case 'H': 
  249. XX            gethelp(argv[0], 0);
  250. XX        case 'n': case 'N': 
  251. XX            NUMBER = TRUE;
  252. XX            break;
  253. XX        case 'w': case 'W': 
  254. XX            WIDE = TRUE;
  255. XX            break;
  256. XX        case 'v': case 'V': 
  257. XX            VERBOSE = TRUE;
  258. XX            break;
  259. XX        case 'f': case 'F': 
  260. XX            FROM = TRUE;
  261. XX            if (cp[2]) 
  262. XX                sprintf(from, "%.79s", &argv[i][2]);
  263. XX            else 
  264. XX            if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
  265. XX                sprintf(from, "%.79s", argv[i+1]);
  266. XX                i++;
  267. XX            }
  268. XX            else
  269. XX            sprintf(from, "%.79s", user);
  270. XX            lfrom = strlen(from);
  271. XX            break;
  272. XX        case 't': case 'T': 
  273. XX            TO = TRUE;
  274. XX            if (cp[2]) 
  275. XX                sprintf(to, "%.79s", &argv[i][2]);
  276. XX            else 
  277. XX            if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
  278. XX                sprintf(to, "%.79s", argv[i+1]);
  279. XX                i++;
  280. XX            }
  281. XX            else
  282. XX            sprintf(to, "%.79s", user);
  283. XX            lto = strlen(to);
  284. XX            break;
  285. XX        case 'd': case 'D': 
  286. XX            DONT = TRUE;
  287. XX            if (cp[2]) 
  288. XX                sprintf(dont, "%.79s", &argv[i][2]);
  289. XX            else 
  290. XX            if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
  291. XX                sprintf(dont, "%.79s", argv[i+1]);
  292. XX                i++;
  293. XX            }
  294. XX            else 
  295. XX            sprintf(dont, "%c", '\0');
  296. XX            ldont = strlen(dont);
  297. XX            if (!ldont) DONT = FALSE;
  298. XX            break;
  299. XX        default: 
  300. XX            printf("invalid option '%c': ", cp[1]);
  301. XX            gethelp(argv[0], -1);
  302. XX    }    /* end switch */
  303. XX    else 
  304. XX    {
  305. XX        gethelp(argv[0], 0);
  306. XX    }    /* end for/if */
  307. XX
  308. XX    /* find the mqueue directory. 
  309. XX     */
  310. XX    qcnt = 0;
  311. XX#ifndef DEBUG
  312. XX    if ( !(fp = fopen("/usr/lib/sendmail.cf", "r")) ) {
  313. XX        printf("fatal error: ");
  314. XX        printf("unable to read /usr/lib/sendmail.cf\n");
  315. XX        gethelp(argv[0], 1);
  316. XX    }
  317. XX    while ((fg = fgets(line, LSIZE, fp)) != (char *) NULL) {
  318. XX        if (strncmp(fg, "OQ", 2)) continue;
  319. XX        fg[strlen(line)-1] = '\0';
  320. XX        fg += 2;
  321. XX        qcnt++;
  322. XX        qdlen = strlen(fg) + 1;
  323. XX        qdir = MALLOC(qdlen);
  324. XX        strncpy(qdir, fg, qdlen - 1);
  325. XX        break;
  326. XX    }
  327. XX    fclose(fp);
  328. XX#endif /* DEBUG */
  329. XX    if (!qcnt) {
  330. XX        qdlen = strlen(MQUEUE) + 1;
  331. XX        qdir = MALLOC(qdlen);
  332. XX        strncpy(qdir, MQUEUE, qdlen - 1);
  333. XX    }
  334. XX
  335. XX    /* find queue files in the mqueue directory: 
  336. XX     * save the location in the directory stream, the queue id and 
  337. XX     * the time for each vaild (non-zero length) queue control file.
  338. XX     */
  339. XX    if ( !(dp = opendir(qdir)) ) {
  340. XX        printf("fatal error: ");
  341. XX        printf("unable to open directory %s\n", qdir);
  342. XX        gethelp(argv[0], 2);
  343. XX    }
  344. XX    mcnt = qcnt = 0;
  345. XX    for (dirp = readdir(dp); dirp != (struct direct *) NULL; 
  346. XX         dirp = readdir(dp)) 
  347. XX    if (!strncmp(dirp->d_name, "qf", 2)) {
  348. XX        /*
  349. XX         * open the file and test it for validity 
  350. XX         */
  351. XX        cp = MALLOC(qdlen + 1 + strlen(dirp->d_name));
  352. XX        sprintf(cp, "%s/%s", qdir, dirp->d_name);
  353. XX        fp = fopen(cp, "r");
  354. XX        VOID stat(cp, &sbuf);
  355. XX        VOID free(cp);
  356. XX        if (!fp) continue;
  357. XX        if (!sbuf.st_size) {
  358. XX            fclose(fp);
  359. XX            continue;
  360. XX        }
  361. XX        /* 
  362. XX         * do book-keeping
  363. XX         */
  364. XX        icnt = 0;
  365. XX        mcnt++;
  366. XX        if (qcnt < NUMQ) 
  367. XX        /*
  368. XX         * check to see if we are supposed to print the entry
  369. XX         */
  370. XX        while ( fg = fgets(line, LSIZE, fp) ) {
  371. XX            fg[strlen(line)-1] = '\0';
  372. XX            if (*fg == 'S') {
  373. XX                if (FROM) {
  374. XX                    for (; *fg; *fg++) 
  375. XX                    if (!strncmp(fg, from, lfrom)) 
  376. XX                    icnt |= 0x001;
  377. XX                } else 
  378. XX                icnt |= 0x001;
  379. XX            } else
  380. XX            if (*fg == 'R') {
  381. XX                if (TO) {
  382. XX                    for (; *fg; *fg++) 
  383. XX                    if (!strncmp(fg, to, lto)) 
  384. XX                    icnt |= 0x002;
  385. XX                } else 
  386. XX                icnt |= 0x002;
  387. XX                if (DONT) {
  388. XX                    for (; *fg; *fg++) 
  389. XX                    if (!strncmp(fg, dont, ldont)) 
  390. XX                    icnt |= 0x004;
  391. XX                } 
  392. XX            }
  393. XX        }    /* end while loop */
  394. XX
  395. XX        if ( (icnt & 0x004) || 
  396. XX            !(icnt & 0x002) || 
  397. XX            !(icnt & 0x001) ) {
  398. XX            /*
  399. XX             * either DONT was specified _and_ we found 
  400. XX             * the dont field in the Receiver field, 
  401. XX             * or TO was specified _and_ we did not find 
  402. XX             * the to field in the Receiver field, 
  403. XX             * or FROM was specified _and_ we did not find 
  404. XX             * the from field in the Sender field; 
  405. XX             * or we have exceeded the array dimension for 
  406. XX             * holding queue information. 
  407. XX             */
  408. XX            fclose(fp);
  409. XX            continue;
  410. XX        }
  411. XX        /*
  412. XX         * save the location in the directory stream
  413. XX         */
  414. XX        qinfo[qcnt].l = telldir(dp);
  415. XX        /*
  416. XX         * save the queue id
  417. XX         */
  418. XX        sprintf(qinfo[qcnt].q, "%.7s", 
  419. XX                index(dirp->d_name, 'f')+1);
  420. XX        /*
  421. XX         * save the queue time
  422. XX         */
  423. XX        VOID fseek(fp, 0L, 0);
  424. XX        while ((fg = fgets(line, LSIZE, fp)) && *fg != 'D') 
  425. XX        if (*fg == 'T') qinfo[qcnt].t = atol(&line[1]);
  426. XX        /*
  427. XX         * increment the valid queue file counter
  428. XX         */
  429. XX        qcnt++;
  430. XX        fclose(fp);
  431. XX    }
  432. XX    closedir(dp);
  433. XX
  434. XX    /* print the requisite header 
  435. XX     */
  436. XX    if (!qcnt) {
  437. XX        if (!mcnt) printf("Mail queue is empty\n");
  438. XX        else {
  439. XX            printf("Mail Queue (%d request%c", 
  440. XX                   mcnt, mcnt > 1 ? 's' : '\0');
  441. XX            printf(", none %s)\n", 
  442. XX                   NUMBER == TRUE ? "applied" : "printed");
  443. XX        }
  444. XX        exit(0);
  445. XX    } 
  446. XX    printf("%sMail Queue (%d request%c", NUMBER == TRUE ? "" : 
  447. XX           ( VERBOSE == TRUE ? "      " : "\t\t" ), 
  448. XX           mcnt, mcnt > 1 ? 's' : '\0');
  449. XX    if (qcnt != mcnt) 
  450. XX    printf(", only %d %s", qcnt, 
  451. XX           NUMBER == TRUE ? "applied" : "printed");
  452. XX    printf(")\n");
  453. XX
  454. XX    if (NUMBER) exit(0);
  455. XX
  456. XX    if (VERBOSE == FALSE) 
  457. XX    printf("%s%s\n", "--QID-- --Size-- -----Q-Time----- ", 
  458. XX           "------------Sender/Recipient-----------------");
  459. XX
  460. XX    /* sort the queue files
  461. XX     */
  462. XX    VOID qsort(qinfo, qcnt, sizeof(struct mqueue), order);
  463. XX
  464. XX    /* loop through the valid queue files: 
  465. XX     */
  466. XX    for (icnt = 0; icnt < qcnt; icnt++) {
  467. XX        cp = MALLOC(qdlen + 2 + strlen(qinfo[icnt].q));
  468. XX        sprintf(cp, "%s/qf%s", qdir, qinfo[icnt].q);
  469. XX        fp = fopen(cp, "r");
  470. XX        VOID free(cp);
  471. XX
  472. XX        /* read in everything up to the first header line
  473. XX         */
  474. XX        mcnt = 0;
  475. XX        while ( fg = fgets(line, LSIZE, fp) ) {
  476. XX
  477. XX            /* get rid of the trailing newline
  478. XX             */
  479. XX            fg[strlen(line)-1] = '\0';
  480. XX
  481. XX            /* get the size of the data file (long)
  482. XX             */
  483. XX            if (*fg == 'D') {
  484. XX                cp = MALLOC(qdlen + strlen(fg));
  485. XX                sprintf(cp, "%s/%s", qdir, &line[1]);
  486. XX                VOID stat(cp, &sbuf);
  487. XX                size = (long) sbuf.st_size;
  488. XX                VOID free(cp);
  489. XX            } else 
  490. XX            /*
  491. XX             * get the error message (char *)
  492. XX             */
  493. XX            if (*fg == 'M') {
  494. XX                message = MALLOC(strlen(fg));
  495. XX                sprintf(message, "%s", &line[1]);
  496. XX                mcnt++;
  497. XX            } else 
  498. XX            /*
  499. XX             * get the sender (char *)
  500. XX             */
  501. XX            if (*fg == 'S') {
  502. XX/*
  503. XX * print out what we have so far 
  504. XX */
  505. XXif (VERBOSE) {
  506. XX    if (WIDE) printf("from: %s\n", &line[1]);
  507. XX    else printf("from: %.73s\n", &line[1]);
  508. XX} else {
  509. XX    printf("%-7.7s %8ld %.16s ", 
  510. XX           qinfo[icnt].q, size, ctime(&qinfo[icnt].t));
  511. XX    if (WIDE) {
  512. XX        printf("%s\n", &line[1]);
  513. XX        if (mcnt) printf("\t\t\t\t  (%s)\n", message);
  514. XX    } else {
  515. XX        printf("%.45s\n", &line[1]);
  516. XX        if (mcnt) printf("\t\t\t\t  (%.43s)\n", message);
  517. XX    }
  518. XX}
  519. XX                size = 0L;
  520. XX                if (mcnt) VOID free(message);
  521. XX            } else 
  522. XX            /*
  523. XX             * get the recipients (char *)
  524. XX             */
  525. XX            if (*fg == 'R') {
  526. XX                /*
  527. XX                 * print out the rest
  528. XX                 */
  529. XX                if (VERBOSE) {
  530. XX                    printf("      to: ");
  531. XX                    if (WIDE) 
  532. XX                    printf("%s\n", &line[1]);
  533. XX                    else 
  534. XX                    printf("%.69s\n", &line[1]);
  535. XX                } else {
  536. XX                    printf("\t\t\t\t  ");
  537. XX                    if (WIDE) 
  538. XX                    printf("%s\n", &line[1]);
  539. XX                    else 
  540. XX                    printf("%.45s\n", &line[1]);
  541. XX                }
  542. XX            }
  543. XX
  544. XX        }    /* end fp loop */
  545. XX        fclose(fp);
  546. XX
  547. XX        if (VERBOSE) printf("      in queue since: %.16s\n", 
  548. XX                            ctime(&qinfo[icnt].t));
  549. XX
  550. XX    }    /* end valid queue file loop */
  551. XX
  552. XX    exit(0);
  553. XX}
  554. XX
  555. XX/* qsort comparison function. 
  556. XX */
  557. XXint 
  558. XXorder(e1, e2)
  559. XXstruct mqueue *e1;
  560. XXstruct mqueue *e2;
  561. XX{
  562. XX#ifdef SORT_BY_TIME
  563. XX    if (e1->t < e2->t) return(-1);
  564. XX    else if (e1->t > e2->t) return(1);
  565. XX    else return(0);
  566. XX#endif
  567. XX#ifdef SORT_BY_ID
  568. XX    return(strcmp(e1->q, e2->q));
  569. XX#endif
  570. XX}
  571. XX
  572. XX/* the help/usage message 
  573. XX */
  574. XXstatic 
  575. XXint 
  576. XXgethelp(program, exit_status)
  577. XXchar *program;
  578. XXint exit_status;
  579. XX{
  580. XX    register char *name;
  581. XX
  582. XX    name = rindex(program, '/');
  583. XX    if (name) *name++;
  584. XX    else {
  585. XX        name = rindex(program, '\\');
  586. XX        if (name) *name++;
  587. XX        else name = program;
  588. XX    }
  589. XX    printf("usage: %s [-w] [-n] [-v]", name);
  590. XX    printf(" [-f [name]] [-t [name]] [-d name]\n");
  591. XX    exit(exit_status);
  592. XX}
  593. XX
  594. SHAR_EOF
  595. if test 9946 -ne "`wc -c < mq.c`"
  596. then
  597.   echo shar: error transmitting "mq.c" '(should have been 9946 characters)'
  598. fi
  599. fi # end of overwriting check
  600. echo shar: extracting "from.c" '(6741 characters)'
  601. if test -f from.c
  602. then
  603.   echo shar: will not over-write existing file "from.c"
  604. else
  605. sed 's/^XX//' << \SHAR_EOF > from.c
  606. XX/*
  607. XX * usage:
  608. XX *      from [-f] [file] [-d] [-w] [-s sender] [-u user]
  609. XX *
  610. XX * caveats/comments:
  611. XX *    no checking is done w.r.t. what other programs are doing to the 
  612. XX *    mailboxes.
  613. XX *
  614. XX * author:
  615. XX *    Kevin Sweet ---------------------------------- sweet@scubed.arpa
  616. XX *    S-CUBED, 3398 Carmel Mountain,  San Diego, CA 92121-1095
  617. XX *    (home)  12205 Carmel Vista 242, San Diego, CA 92130-2237
  618. XX *    ------- [ames,att,harvard,rutgers,ucsd,uunet]scubed!sweet ------
  619. XX *
  620. XX * This work is copyright 1988 by Kevin Sweet. Permission is granted 
  621. XX * to modify and distribute this work under the provision that the 
  622. XX * author is informed of any non-cosmetic changes to the code and that 
  623. XX * the author's name remain part of the documentaion. 
  624. XX */
  625. XX
  626. XX#ifdef SYSV
  627. XX# define MAXPATHLEN    1024
  628. XX# include <string.h>
  629. XX# define index        strchr
  630. XX# define rindex        strrchr
  631. XX#else
  632. XX# include <sys/param.h>
  633. XX# include <strings.h>
  634. XX#endif
  635. XX#include <stdio.h>
  636. XX
  637. XXextern char *getenv();
  638. XXstatic char *getmbox();
  639. XXstatic int gethelp();
  640. XX
  641. XX#define FORWARD        0
  642. XX#define LSIZE        256
  643. XX#define NUMQ        256
  644. XX#define SWITCHAR    '-'
  645. XX
  646. XXstruct mbox {
  647. XX    char from[LSIZE];
  648. XX    char subject[LSIZE];
  649. XX};
  650. XX
  651. XXmain(argc, argv)
  652. XXint argc;
  653. XXchar *argv[];
  654. XX{
  655. XX    FILE *fp;
  656. XX    char line[LSIZE], mbox[MAXPATHLEN], path[LSIZE], sender[LSIZE];
  657. XX    register char *bang, *cp;
  658. XX    register int DATE, SENDER, WIDE, 
  659. XX                 from, i, j, left, mcnt, subject;
  660. XX    struct mbox mail[NUMQ];
  661. XX
  662. XX    /* find the mail file to list along with any options
  663. XX     */
  664. XX    strcpy(mbox, "\0");
  665. XX    DATE = SENDER = WIDE = 0;
  666. XX    for (i = 1, cp = argv[1]; i < argc; i++, cp = argv[i]) {
  667. XX
  668. XX        if (cp[0] == SWITCHAR) 
  669. XX        switch (cp[1]) {
  670. XX        case 'h': case 'H': 
  671. XX            gethelp(argv[0], 0);
  672. XX        case 'd': case 'D': 
  673. XX            DATE = 1;
  674. XX            break;
  675. XX        case 'w': case 'W': 
  676. XX            WIDE ++;
  677. XX            if (cp[2] == 'w' || cp[2] == 'W') WIDE++;
  678. XX            break;
  679. XX        case 'f': case 'F': 
  680. XX            if (cp[2]) 
  681. XX                strncpy(mbox, &argv[i][2], MAXPATHLEN);
  682. XX            else 
  683. XX            if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
  684. XX                strncpy(mbox, argv[i+1], MAXPATHLEN);
  685. XX                i++;
  686. XX            }
  687. XX            else 
  688. XX            strncpy(mbox, getmbox(), MAXPATHLEN);
  689. XX            break;
  690. XX        case 's': case 'S': 
  691. XX            if (cp[2]) 
  692. XX                strncpy(sender, &argv[i][2], LSIZE);
  693. XX            else 
  694. XX            if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
  695. XX                strncpy(sender, argv[i+1], LSIZE);
  696. XX                i++;
  697. XX            }
  698. XX            else 
  699. XX#ifdef SYSV
  700. XX            strncpy(sender, getenv("LOGNAME"), LSIZE);
  701. XX#else
  702. XX            strncpy(sender, getenv("USER"), LSIZE);
  703. XX#endif
  704. XX            SENDER = strlen(sender);
  705. XX            break;
  706. XX        case 'u': case 'U': 
  707. XX            if (cp[2]) {
  708. XX                strncpy(mbox, MAILDIR, MAXPATHLEN);
  709. XX                strncat(mbox, &argv[i][2], 
  710. XX                        MAXPATHLEN - strlen(mbox));
  711. XX            }
  712. XX            else 
  713. XX            if (i != argc-1 || argv[i+1][0] != SWITCHAR) {
  714. XX                strncpy(mbox, MAILDIR, MAXPATHLEN);
  715. XX                strncat(mbox, argv[i+1], 
  716. XX                        MAXPATHLEN - strlen(mbox));
  717. XX                i++;
  718. XX            }
  719. XX            else
  720. XX            strcpy(mbox, "\0");
  721. XX            break;
  722. XX        default: 
  723. XX            printf("invalid option '%c': ", cp[1]);
  724. XX            gethelp(argv[0], -1);
  725. XX        }    /* end if/switch */
  726. XX        else 
  727. XX        strncpy(mbox, argv[i], MAXPATHLEN);
  728. XX
  729. XX    }    /* end for */
  730. XX
  731. XX    /* use the system mailbox if there are no arguments or if 
  732. XX     * there are any (fatal) errors
  733. XX     */
  734. XX    if (!strlen(mbox)) {
  735. XX        strncpy(mbox, MAILDIR, MAXPATHLEN);
  736. XX#ifdef SYSV
  737. XX        strncat(mbox, getenv("LOGNAME"), 
  738. XX#else
  739. XX        strncat(mbox, getenv("USER"), 
  740. XX#endif
  741. XX                MAXPATHLEN - strlen(mbox));
  742. XX    } 
  743. XX
  744. XX    /* if we can't open the mailbox, exit quitely
  745. XX     */
  746. XX    fp = fopen(mbox, "r");
  747. XX    if (!fp) exit(1);
  748. XX
  749. XX    /* read in the sender and subject of each letter
  750. XX     */
  751. XX    mcnt = -1;
  752. XX    while ( cp = fgets(line, LSIZE, fp) ) {
  753. XX        cp[strlen(line)-1] = '\0';
  754. XX        if (!strncmp(line, "From ", 5)) {
  755. XX            if (mcnt >= 0 && !strlen(mail[mcnt].from)) 
  756. XX               strcpy(mail[mcnt].from, path);
  757. XX            strcpy(path, index(line, ' ')+1);
  758. XX            if (!DATE) {
  759. XX                cp = index(path, ' ');
  760. XX                if (cp) cp[0] = '\0';
  761. XX            }
  762. XX            if (SENDER) {
  763. XX                from = 1;
  764. XX                subject = 1;
  765. XX                cp = path;
  766. XX                j = 0;
  767. XX                for (; *cp; *cp++) 
  768. XX                if (!strncmp(cp, sender, SENDER)) j++;
  769. XX            } else 
  770. XX            j = 1;
  771. XX            if (j) {
  772. XX                mcnt++;
  773. XX                from = 0;
  774. XX                subject = 0;
  775. XX            }
  776. XX        } else 
  777. XX        if (!from && ( !strncmp(line, "From: ", 6) || 
  778. XX            !strncmp(line+1, "From: ", 6) )) {
  779. XX            if (!FORWARD) from = 1;
  780. XX            if (DATE || WIDE > 1) {
  781. XX                strcpy(mail[mcnt].from, path);
  782. XX                continue;
  783. XX            }
  784. XX            cp = index(line, '<');
  785. XX            if (cp) *cp++;
  786. XX            else cp = index(line, ' ')+1;
  787. XX            strcpy(mail[mcnt].from, cp);
  788. XX            cp = index(mail[mcnt].from, '>');
  789. XX            if (!cp) cp = index(mail[mcnt].from, ' ');
  790. XX            if (cp) cp[0] = '\0';
  791. XX        } else 
  792. XX        if (!subject && !strncmp(line, "Subject: ", 9)) {
  793. XX            if (!FORWARD) subject = 1;
  794. XX            strcpy(mail[mcnt].subject, index(line, ' ')+1);
  795. XX            if (DATE && !WIDE) 
  796. XX               strcpy(mail[mcnt].subject, "\0");
  797. XX        } 
  798. XX    }
  799. XX    if (!strlen(mail[mcnt].from)) strcpy(mail[mcnt].from, path);
  800. XX
  801. XX    /* display each entry: 
  802. XX     * if this isn't a wide list, use the shortest available name 
  803. XX     * for the sender and make sure that the subject does not 
  804. XX     * wrap 80 columns 
  805. XX     */
  806. XX    for (i = 0; i <= mcnt; i++) {
  807. XX        cp = index(mail[i].from, '!');
  808. XX        bang = rindex(mail[i].from, '!');
  809. XX        if (!DATE && WIDE < 2) {
  810. XX            if (!bang || !strcmp(cp, bang)) 
  811. XX               cp = mail[i].from;
  812. XX            else 
  813. XX            {
  814. XX                cp++;
  815. XX                while (strcmp(index(cp, '!'), bang)) {
  816. XX                    cp = index(cp, '!');
  817. XX                    cp++;
  818. XX                }    /* end while */
  819. XX            }
  820. XX        } else 
  821. XX               cp = mail[i].from;
  822. XX        left = 71 - (int) strlen(cp);
  823. XX        printf("From %s", cp);
  824. XX        if (DATE && !WIDE) putchar('\n');
  825. XX        else 
  826. XX        if (strlen(mail[i].subject)) {
  827. XX            printf(", ");
  828. XX            if (!WIDE) {
  829. XX                putchar('"');
  830. XX                cp = mail[i].subject;
  831. XX                for (j = 0; j < left; j++) 
  832. XX                    if (*cp) putchar(*cp++);
  833. XX                printf("\"\n");
  834. XX            } else 
  835. XX            printf("\"%s\"\n", mail[i].subject);
  836. XX        } 
  837. XX        else
  838. XX        printf(", (no subject)\n");
  839. XX    } 
  840. XX
  841. XX    fclose(fp);
  842. XX}
  843. XX
  844. XXstatic 
  845. XXchar *
  846. XXgetmbox()
  847. XX{
  848. XX    FILE *fp;
  849. XX    char line[LSIZE], mailrc[MAXPATHLEN], mbox[MAXPATHLEN];
  850. XX    register char *cp;
  851. XX
  852. XX    /* find out where to look for mail startup file
  853. XX     */
  854. XX    strncpy(mailrc, getenv("HOME"), MAXPATHLEN);
  855. XX    strncat(mailrc, "/.mailrc", MAXPATHLEN - strlen(mailrc));
  856. XX    if (getenv("MAILRC")) 
  857. XX        strncpy(mailrc, getenv("MAILRC"), MAXPATHLEN);
  858. XX
  859. XX    /* find out where to look for the default mailbox
  860. XX     */
  861. XX    strncpy(mbox, getenv("HOME"), MAXPATHLEN);
  862. XX    strncat(mbox, "/mbox", MAXPATHLEN - strlen(mbox));
  863. XX    fp = fopen(mailrc, "r");
  864. XX    if (fp) {
  865. XX        while ( cp = fgets(line, LSIZE, fp) ) {
  866. XX            cp[strlen(line)-1] = '\0';
  867. XX            if (strncmp(line, "set MBOX=", 9)) continue;
  868. XX            cp += 9;
  869. XX            strncpy(mbox, cp, MAXPATHLEN);
  870. XX            break;
  871. XX        }
  872. XX        fclose(fp);
  873. XX    }
  874. XX    if (getenv("MBOX")) 
  875. XX        strncpy(mbox, getenv("MBOX"), MAXPATHLEN);
  876. XX
  877. XX    return(mbox);
  878. XX}
  879. XX
  880. XX/* the help/usage message 
  881. XX */
  882. XXstatic 
  883. XXint 
  884. XXgethelp(program, exit_status)
  885. XXchar *program;
  886. XXint exit_status;
  887. XX{
  888. XX    register char *name;
  889. XX
  890. XX    name = rindex(program, '/');
  891. XX    if (name) *name++;
  892. XX    else {
  893. XX        name = rindex(program, '\\');
  894. XX        if (name) *name++;
  895. XX        else name = program;
  896. XX    }
  897. XX    printf("usage: %s [-f] [file] ", name);
  898. XX    printf("[-d] [-w] [-s sender] [-u user]\n");
  899. XX    exit(exit_status);
  900. XX}
  901. XX
  902. SHAR_EOF
  903. if test 6741 -ne "`wc -c < from.c`"
  904. then
  905.   echo shar: error transmitting "from.c" '(should have been 6741 characters)'
  906. fi
  907. fi # end of overwriting check
  908. echo shar: extracting "from.1" '(2208 characters)'
  909. if test -f from.1
  910. then
  911.   echo shar: will not over-write existing file "from.1"
  912. else
  913. sed 's/^XX//' << \SHAR_EOF > from.1
  914. XX.de KS
  915. XX.if t .B \\$1 \\$2
  916. XX.if n .I \\$1 \\$2
  917. XX..
  918. XX.de UL
  919. XX.if t \\$1\l'|0\(ul'\\$2
  920. XX.if n .I \\$1 \\$2
  921. XX..
  922. XX.de Sh
  923. XX.PP
  924. XX\fB\\$1\fR
  925. XX.PP
  926. XX..
  927. XX.TH FROM 1L local "22 April 1988"
  928. XX.SH NAME
  929. XXfrom \- list sender and subject of mail
  930. XX.SH SYNTAX
  931. XX.B from
  932. XX[\fB\-f\fR]
  933. XX[\fBfile\fR]
  934. XX[\fB\-d\fR]
  935. XX[\fB\-w\fR]
  936. XX[\fB\-s\fR [sender]]
  937. XX[\fB\-u\fR user]
  938. XX.SH DESCRIPTION
  939. XX.I From
  940. XXlists an abbreviated name for the sender of each letter in the
  941. XXspecified mail file
  942. XX.KS file
  943. XX(which 
  944. XX.UL may 
  945. XXbe preceded or prepended on the command line by \fB\-f\fR)
  946. XXalong with the subject of the letter so that both sets of information
  947. XXcan fit into 80 columns of standard output.
  948. XX.Sh Options
  949. XXWith no options, \fIfrom\fR lists the mail in the user's system mailbox.
  950. XX.TP 1i
  951. XX.B \-f
  952. XXIf 
  953. XX.KS file
  954. XXis not specified, then mail in the file \fImbox\fR in
  955. XXthe user's home directory is listed (see ENVIRONMENT section for
  956. XXfurther details).
  957. XXOtherwise, mail in the mailbox
  958. XX.I file
  959. XXis listed.
  960. XX.TP
  961. XX.B \-h
  962. XXPrint the \fIfrom\fR syntax.
  963. XX.TP
  964. XX.B \-d
  965. XXThe complete return path and the date received are displayed.
  966. XX(This duplicates \fI/usr/ucb/from\fR.)
  967. XX.TP
  968. XX.B \-w
  969. XXThe \fB\-w\fR option is similar to that for \fIps\fR on BSD systems.
  970. XXSelecting \fB\-w\fR displays each entry in long form (in this case,
  971. XXa minimalist sender's address and the full subject);
  972. XXwhereas, \fB\-ww\fR displays each entry in unabridged form (i.e., the
  973. XXfull subject and the complete return path for the sender are listed).
  974. XX.TP
  975. XX.BR \-s " sender"
  976. XXOnly mail from \fIsender\fR is listed. \fISender\fR defaults to
  977. XX$LOGNAME on System V and to $USER on BSD systems.
  978. XX.TP
  979. XX.BR \-u " user"
  980. XXMail in \fIuser\fR's system mailbox is listed.
  981. XX.SH ENVIRONMENT
  982. XX.I From
  983. XXuses the following environment variables:
  984. XX.TP 1.375i
  985. XXHOME
  986. XXThe user's home (default login) directory.
  987. XX.TP
  988. XXUSER/LOGNAME
  989. XXThe user's user (login) name.
  990. XX.PP
  991. XXIf the environment variable MAILRC is set,
  992. XX.I from
  993. XXwill check the mail startup file specified by $MAILRC instead of
  994. XX\fI$HOME/.mailrc\fR.
  995. XXIf the environment variable MBOX is set,
  996. XX.I from
  997. XXwill recognize the default mailbox specified by $MBOX rather than
  998. XXthat specified in the mail startup file
  999. XXor
  1000. XX\fI$HOME/mbox\fR.
  1001. XX.SH "SEE ALSO"
  1002. XX.ta 12n
  1003. XXBSD \-    \fIMail\fR(1)
  1004. XX.br
  1005. XXSystem V \-    \fImailx\fR(1)
  1006. XX.SH AUTHOR
  1007. XXKevin Sweet
  1008. SHAR_EOF
  1009. if test 2208 -ne "`wc -c < from.1`"
  1010. then
  1011.   echo shar: error transmitting "from.1" '(should have been 2208 characters)'
  1012. fi
  1013. fi # end of overwriting check
  1014. echo shar: extracting "mq.8" '(1850 characters)'
  1015. if test -f mq.8
  1016. then
  1017.   echo shar: will not over-write existing file "mq.8"
  1018. else
  1019. sed 's/^XX//' << \SHAR_EOF > mq.8
  1020. XX.de KS
  1021. XX.if t .B \\$1 \\$2
  1022. XX.if n .I \\$1 \\$2
  1023. XX..
  1024. XX.de UL
  1025. XX.if t \\$1\l'|0\(ul'\\$2
  1026. XX.if n \\$1 \\$2
  1027. XX..
  1028. XX.de Sh
  1029. XX.PP
  1030. XX\fB\\$1\fR
  1031. XX.PP
  1032. XX..
  1033. XX.TH MQ 8L local "22 April 1988"
  1034. XX.SH NAME
  1035. XXmq \- print the contents of the mail queue
  1036. XX.SH SYNTAX
  1037. XX.B mq
  1038. XX[\fB\-w\fR]
  1039. XX[\fB\-n\fR]
  1040. XX[\fB\-v\fR]
  1041. XX[\fB\-f\fR [name]]
  1042. XX[\fB\-t\fR [name]]
  1043. XX[\fB\-d\fR name]
  1044. XX.SH DESCRIPTION
  1045. XXBy default,
  1046. XX.I mq
  1047. XXlists the contents of the mail queue in the same format as
  1048. XX.I sendmail
  1049. XXwhen invoked as \fImailq\fR except that 
  1050. XXitems in the queue without a control file are not displayed by \fImq\fR.
  1051. XXThat is,
  1052. XXit displays an error message (if any), the queue identification code, 
  1053. XXfile size, queue time, sender, and recipient(s) for each entry in the
  1054. XXqueue
  1055. XXso that the result can fit into 80 columns of standard output.
  1056. XX.Sh Options
  1057. XX.TP 1i
  1058. XX.B \-f
  1059. XX\fBfrom\fR.
  1060. XXIf 
  1061. XX.KS name
  1062. XXis specified, \fImq\fR lists only messages with 
  1063. XX.KS name
  1064. XXin the `sender' field. Otherwise, \fImq\fR will list only messages
  1065. XXwith the user's login name (as given by the environment variable
  1066. XXLOGNAME on System V and by USER on BSD systems) in the `sender' field.
  1067. XX.TP
  1068. XX.B \-t
  1069. XX\fBto\fR.
  1070. XXIf 
  1071. XX.KS name
  1072. XXis specified, \fImq\fR lists only messages with 
  1073. XX.KS name
  1074. XXin the `recipient' field. Otherwise, \fImq\fR will list only messages
  1075. XXwith $USER/$LOGNAME in the `recipient' field.
  1076. XX.TP
  1077. XX.BR \-d " name"
  1078. XX\fBdon't\fR.
  1079. XXList all messages that 
  1080. XX.UL "do not"
  1081. XXcontain the string 
  1082. XX.KS name
  1083. XXin the `recipient' field.
  1084. XX.TP
  1085. XX.B \-h
  1086. XX\fBhelp\fR.
  1087. XXPrint the \fImq\fR syntax.
  1088. XX.TP
  1089. XX.B \-w
  1090. XX\fBwide\fR.
  1091. XX.I Mq
  1092. XXwill not truncate `sender' and `recipient' fields on output.
  1093. XX.TP
  1094. XX.B \-n
  1095. XX\fBnumber\fR.
  1096. XXList only a count of the selected files in the mail queue.
  1097. XX.TP
  1098. XX.B \-v
  1099. XX\fBverbose\fR.
  1100. XXDisplay the contents of the mail queue listing the sender,
  1101. XXrecipient(s) and queue time in noncolumnar format.
  1102. XX.SH FILES
  1103. XX/usr/lib/sendmail.cf
  1104. XX.SH "SEE ALSO"
  1105. XX\fIsendmail\fR(8)
  1106. XX.SH AUTHOR
  1107. XXKevin Sweet
  1108. SHAR_EOF
  1109. if test 1850 -ne "`wc -c < mq.8`"
  1110. then
  1111.   echo shar: error transmitting "mq.8" '(should have been 1850 characters)'
  1112. fi
  1113. fi # end of overwriting check
  1114. #
  1115. # End of shell archive
  1116. exit 0
  1117. --
  1118.  
  1119.